#pragma once
#include <game/Config.h>
#include <game/flow/EntryDefinition.h>
#include <game/flow/SelectorFactory.h>
#include <game/flow/TriggerFactory.h>

#include <xml/Object.h>
#include <AutoContainer.h>
#include <map>
#include <vector>
#include <deque>

ARELLO_GAME_NAMESPACE_DECL_START
class Root;
namespace flow {

class TriggerEntry;

class Manager
	: private xml::ObjectANSI
{
	friend class TriggerEntry;
public:
	typedef std::string Key;

	Manager();
	virtual ~Manager();

	xml::ObjectANSI* GetLoader() { return this; }

	flow::EntryDefinition* CreateStartEntry();
	flow::EntryDefinition* SwitchScreen(flow::EntryDefinition* currentEntry, const Key& exitId);

	void SetSelectorFactory(const SelectorFactory& value) { this->selectorFactory = value; }
	void SetTriggerFactory(const TriggerFactory& value) { this->triggerFactory = value; }
	void SetRoot(Root* value) { this->root = value; }
private:
	typedef std::deque<flow::EntryDefinition*> EntryQueue;
	typedef std::map<Key, flow::EntryDefinition*> Entries;
	typedef AutoContainer<std::vector<TriggerEntry*> > Triggers;
	friend void checkLinks(Manager::Entries& entries);
	void doSwitchScreen(flow::EntryDefinition* currentEntry, const Key& exitId);

	virtual bool on_attribute(xml::Provider * prov, const std::string & name, const std::string & value);
	virtual bool on_node(xml::Provider * prov, const std::string & name);
	virtual bool on_end_node(xml::Provider * prov);

	void switchSpecialScreen(const Key& exitId);
	void pushEntry(flow::EntryDefinition* entry);
	flow::EntryDefinition* advance();

	/** Manager owns all entries from this collection */
	Entries entries;
	Triggers triggers;
	EntryQueue queue;
	std::string start;
	flow::SelectorFactory selectorFactory;
	flow::TriggerFactory triggerFactory;

	Root* root;
};

} // namespace flow
ARELLO_GAME_NAMESPACE_DECL_END